package top.mengchaob.maven;

import org.apache.maven.shared.invoker.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import top.mengchaob.util.PropUtil;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Arrays;

/**
 * @title：
 * @author: mengchaob
 * @date: 2021年06月01日 9:37
 * @description:
 * 在所有项目pom中（父子项目的父项目pom）,中添加如下配置
 *      <properties>
 *         <!--定义输出目录-->
 *         <outputDirectory>D:\\gitWorkSpace\\output</outputDirectory>
 *     </properties>
 *  在输出包的路径下需要增加如下配置
 *   <plugin>
 *       <groupId>org.springframework.boot</groupId>
 *       <artifactId>spring-boot-maven-plugin</artifactId>
 *            <configuration>
 *                  <outputDirectory>${outputDirectory}</outputDirectory>
 *             </configuration>
 *   </plugin>
 *   主要是配置outputDirectory标签，来确定输入目录
 */
@Component("mvnUtil")
public class MvnUtil {
    Logger logger = LoggerFactory.getLogger(MvnUtil.class);
    public static void main(String[] args) {
        MvnUtil mvnUtil = new MvnUtil();
//        mvnUtil.appointOutDir();
//        mvnUtil.packWar("dev");
//        mvnUtil.cleanByBranchName(PropUtil.getV("maven.localOutDir")+File.separator+"dev-test");
    }
    public void cleanByBranchName(String fileurl){
        File file = new File(fileurl);
        if(file.isDirectory()){
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                if(files[i].isFile()){
                    files[i].delete();
                }else {
                    cleanByBranchName(files[i].getAbsolutePath());
                }
            }
        }

    }
    public synchronized void appointOutDir(){
        File file = new File(PropUtil.getV("maven.localOutDir"));
        if(!file.exists()){
            file.mkdir();
        }
        //1.创建DocumentBuilderFactory对象
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //2.创建DocumentBuilder对象
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document d = builder.parse(PropUtil.getV("maven.pomFile"));
            NodeList sList = d.getElementsByTagName("plugin");
            for (int i = 0; i < sList.getLength(); i++) {
                //为每一个节点设置导出包路径
                Node plugin = sList.item(i);
                NodeList pluginChildNodes = plugin.getChildNodes();
                boolean isConfExist = false;
                int  confIndex = 0;
                for (int j = 0; j < pluginChildNodes.getLength(); j++) {
                    Node child = pluginChildNodes.item(j);
                    if(child.getNodeName().equals("configuration")){
                        isConfExist=true;
                        confIndex = j;
                        break;
                    }
                }

                if(!isConfExist){
                    //不存在configuration，则创建节点
                    Node configuration = d.createElement("configuration");
                    Node outputDirectory = d.createElement("outputDirectory");
                    //创建文本
                    Text text = d.createTextNode(PropUtil.getV("maven.localOutDir"));
                    outputDirectory.appendChild(text);
                    configuration.appendChild(outputDirectory);
                    plugin.appendChild(configuration);

                }else {
                    Node configuration = pluginChildNodes.item(confIndex);
                    NodeList configurationChildNodes = configuration.getChildNodes();
                    boolean isOutPutExist = false;
                    int outPutIndex = 0;
                    for (int j = 0; j < configurationChildNodes.getLength(); j++) {
                        Node tmp = configurationChildNodes.item(j);
                        if(tmp.getNodeName().equals("outputDirectory")){
                            isOutPutExist=true;
                            outPutIndex=j;
                            break;
                        }
                    }
                    if(isOutPutExist){
                        //存在configuration,但是没有outputDirectory
                        //不存在configuration，则创建节点
                        Node outputDirectory = d.createElement("outputDirectory");
                        //创建文本
                        Text text = d.createTextNode(PropUtil.getV("maven.localOutDir"));
                        outputDirectory.appendChild(text);
                        configuration.appendChild(outputDirectory);
                    }else {
                        //存在configuration,存在outputDirectoy,修改到选定目录
                        Node outputDirectory = configurationChildNodes.item(outPutIndex);
                        outputDirectory.setTextContent(PropUtil.getV("maven.localOutDir"));
                    }
                }

            }
            // 把构造的XML结构，写入到具体的文件中
            TransformerFactory formerFactory=TransformerFactory.newInstance();
            Transformer transformer=formerFactory.newTransformer();
            // 换行
            transformer.setOutputProperty(OutputKeys.INDENT, "YES");
            // 文档字符编码
            transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
            // 本分原来文件
            this.copyNio(PropUtil.getV("maven.pomFile"),PropUtil.getV("maven.pomFile")+"bake");
            // 可随意指定文件的后缀,效果一样,但xml比较好解析,比如: E:\\person.txt等
            transformer.transform(new DOMSource(d),new StreamResult(new File(PropUtil.getV("maven.pomFile"))));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public synchronized void packWar(String branchName){
        /**
         *  将生成的包移动到文件服务器
         */
        String fileString = PropUtil.getV("baseUrl")+File.separator+branchName;
        File file = new File(fileString);
        if(file.exists()){
            if(file.isFile()){
                throw new RuntimeException(fileString+"不是一个目录！");
            }
        }else{
            file.mkdir();
        }
        InvocationRequest request = new DefaultInvocationRequest();
        request.setShowErrors(true);
        request.setLocalRepositoryDirectory(new File(PropUtil.getV("maven.localRepositoryDirectory")));
        request.setPomFile(new File(PropUtil.getV("maven.pomFile")));
        request.setGoals(Arrays.asList("clean","package","-Dmaven.javadoc.skip=true","-DskipTests","-DoutputDirectory="+fileString));
        Invoker invoker = new DefaultInvoker();
        invoker.setMavenHome(new File(PropUtil.getV("maven.home")));
        try {
            InvocationResult result = invoker.execute(request);
            System.out.println(request.getBuilder());
            System.out.println("ExitCode:" + result.getExitCode());
            if(result.getExecutionException()!=null) {
                System.out.println("Exception:" + result.getExecutionException().getMessage());
            }
        } catch (MavenInvocationException e) {
            e.printStackTrace();
        }
    }

    public void copyNio(String source, String dest) {
        FileChannel input = null;
        FileChannel output = null;

        try {
            input = new FileInputStream(new File(source)).getChannel();
            output = new FileOutputStream(new File(dest)).getChannel();
            output.transferFrom(input, 0, input.size());
        } catch (Exception e) {
            logger.error("copyNio", "error occur while copy", e);
        } finally {
            if(input.isOpen()){
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (output.isOpen()){
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}